﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Win32;
using System.Windows.Forms;
using System.IO;
using System.Security.Permissions;

namespace Principal
{
    public static class Controlador
    {
        delegate void delegadoNecesario(int valor, ProgressBar miBarra, Form formulario);
        delegate void delegadoNecesarioDatos(int valor, Label informacionBarra, Form formulario, int maximoBarra, string nombreArchivo);

        public static void copiarCarpetas(string origen, string destino, double tamMaxArchivo, double tamMaxCarpeta, string[] extValidas, string[] extNoValidas, Boolean copiarSoloExtValidas, ProgressBar barraProgreso, Form formulario, Label labelDatosBarra)
        {
            //Código agregado por errores en la obtención de los archivos/directorios de origen
            string[] archivosOrigen;
            string[] carpetasOrigen;

            try
            {
                archivosOrigen = System.IO.Directory.GetFiles(origen);
                carpetasOrigen = System.IO.Directory.GetDirectories(origen);
            }
            catch
            {
                archivosOrigen = null;
                carpetasOrigen = null;
            }
            //Fin código agregado
            //Original: 
            //  string[] archivosOrigen = System.IO.Directory.GetFiles(origen);
            //  string[] carpetasOrigen = System.IO.Directory.GetDirectories(origen);
            

            string nombreArchivo = "";
            string nombreCarpeta = "";

            Boolean deboCopiarArchivo;
            System.IO.FileInfo archivoActual;

            if (archivosOrigen != null)
            {
                foreach (string rutaCompletaArchivo in archivosOrigen)
                {
                    //Por cada archivo por defecto no lo copio..
                    deboCopiarArchivo = false;

                    nombreArchivo = obtenerNombreArchivo(rutaCompletaArchivo);

                    archivoActual = new System.IO.FileInfo(rutaCompletaArchivo);

                    if (!System.IO.File.Exists(destino + nombreArchivo))
                    {
                        deboCopiarArchivo = true;
                    }

                    if (System.IO.File.GetLastWriteTime(origen + nombreArchivo) > System.IO.File.GetLastWriteTime(destino + nombreArchivo))
                        deboCopiarArchivo = true;

                    if (archivoActual.Length > (tamMaxArchivo * 1024 * 1024))
                        deboCopiarArchivo = false;

                    if (extValidas != null)
                        if (extValidas.Contains(archivoActual.Extension))
                            deboCopiarArchivo = true;

                    if (extNoValidas != null)
                        if (extNoValidas.Contains(archivoActual.Extension))
                            deboCopiarArchivo = false;

                    if (copiarSoloExtValidas)
                    {
                        if (extValidas.Contains(archivoActual.Extension))
                        {
                            deboCopiarArchivo = true;
                        }
                        else
                            deboCopiarArchivo = false;
                    }

                    if (deboCopiarArchivo)
                        try
                        {
                            System.IO.File.Copy(rutaCompletaArchivo, destino + nombreArchivo, true);
                        }
                        catch //(System.UnauthorizedAccessException ex) ¿Borrar?
                        {
                            //TODO habria que manejar esta excepción..

                            /*
                            FileIOPermission f = new FileIOPermission(PermissionState.Unrestricted);
                            f.AddPathList(FileIOPermissionAccess.AllAccess, rutaCompletaArchivo);
                            f.AddPathList(FileIOPermissionAccess.AllAccess, destino + nombreArchivo);

                            System.IO.File.Copy(rutaCompletaArchivo, destino + nombreArchivo, true);
                            */
             
                        }

                    modificarBarra(Convert.ToInt32(archivoActual.Length / 1024), barraProgreso, formulario);
                    modificarDatosBarra(Convert.ToInt32(archivoActual.Length / 1024), labelDatosBarra, formulario, barraProgreso.Maximum, archivoActual.Name);
                    //MessageBox.Show("Archivo: " + archivoActual.Name + "  Tamaño: " + archivoActual.Length/1024 + "Tamaño total: " + barraProgreso.Maximum);
                }

                foreach (string carpeta in carpetasOrigen)
                {
                    nombreCarpeta = obtenerNombreArchivo(carpeta);
                    double pesoCarpetaEnMB = ObtenerPesoDirectorioEnBytes(new System.IO.DirectoryInfo(carpeta)) / (1024 * 1024);

                    if (!System.IO.Directory.Exists(destino + nombreCarpeta) && tamMaxCarpeta > pesoCarpetaEnMB)
                        System.IO.Directory.CreateDirectory(destino + nombreCarpeta);

                    //Si el tamaño máximo de carpeta que puedo copiar no es superado procedo con la copia..
                    if (tamMaxCarpeta > pesoCarpetaEnMB)
                        copiarCarpetas(origen + nombreCarpeta, destino + nombreCarpeta, tamMaxArchivo, tamMaxCarpeta, extValidas, extNoValidas, copiarSoloExtValidas, barraProgreso, formulario, labelDatosBarra);
                }
            }
        }

        private static long ObtenerPesoDirectorioEnBytes(DirectoryInfo d)
        {

            long pesoDir = 0;

            try
            {

                // Totalizar tamaño de archivos 

                FileInfo[] fis = d.GetFiles();

                foreach (FileInfo fi in fis)
                {

                    pesoDir += fi.Length;

                }

                // Totalizar tamaño sub-directorios 

                DirectoryInfo[] dis = d.GetDirectories();

                foreach (DirectoryInfo di in dis)
                {

                    pesoDir += ObtenerPesoDirectorioEnBytes(di);
                }

            }

            catch
            {

                // Código para la excepción va aquí 

            }

            return pesoDir;

        }

        public static void modificarBarra(int valor, ProgressBar miBarra, Form formulario)
        {
            if (miBarra.InvokeRequired)
            {
                delegadoNecesario del = new delegadoNecesario(modificarBarra);
                formulario.Invoke(del, new object[] { valor, miBarra, formulario });
            }
            else
                if (miBarra.Maximum > (valor + miBarra.Value))
                    miBarra.Value = valor + miBarra.Value;
                else
                    miBarra.Value = miBarra.Maximum;
        }

        public static void modificarDatosBarra(int valor, Label informacionBarra, Form formulario, int maximoBarra, string nombreArchivo)
        {
            if (informacionBarra.InvokeRequired)
            {
                delegadoNecesarioDatos del = new delegadoNecesarioDatos(modificarDatosBarra);
                formulario.Invoke(del, new object[] { valor, informacionBarra, formulario, maximoBarra , nombreArchivo});
            }
            else
                if(informacionBarra.Text != "Finalizado")
                    if (maximoBarra > System.Convert.ToInt64(informacionBarra.Text.Split('/')[0]) + valor)
                    {
                        informacionBarra.Text = "" + (System.Convert.ToInt32(informacionBarra.Text.Split('/')[0]) + valor) + "/" + maximoBarra + "\n" + nombreArchivo;
                        //MessageBox.Show("" + (System.Convert.ToInt32(informacionBarra.Text.Split('/')[0])));
                    }
                    else
                        informacionBarra.Text = "Finalizado";
        }

        private static string obtenerNombreArchivo(string ruta)
        {
            char[] delimitador = { '\\' };
            string[] auxiliar = ruta.Split(delimitador);

            if (auxiliar[auxiliar.Length - 1] != "")
                return "\\" + auxiliar[auxiliar.Length - 1];
            else
                return "\\" + auxiliar[auxiliar.Length - 2];

        }

 

        
    }
}
